package kubeclient

import (
	"fmt"
	"k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/client-go/informers"
	appinformers "k8s.io/client-go/informers/apps/v1"
	v12 "k8s.io/client-go/informers/core/v1"
	v1 "k8s.io/client-go/informers/networking/v1"
	"k8s.io/client-go/kubernetes"
	appslisters "k8s.io/client-go/listers/apps/v1"
	v13 "k8s.io/client-go/listers/core/v1"
	v14 "k8s.io/client-go/listers/networking/v1"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/cache"
	"time"
)

type KubeController struct {
	status        int
	kubeConfig    *rest.Config
	clientSet     *kubernetes.Clientset
	defaultReSync time.Duration
	factory       informers.SharedInformerFactory
	// Deployment
	deploymentInformer appinformers.DeploymentInformer
	deploymentsLister  appslisters.DeploymentLister
	deploymentsSynced  cache.InformerSynced
	// Pod
	podInformer v12.PodInformer
	podLister   v13.PodLister
	podSynced   cache.InformerSynced
	// Service
	serviceInformer v12.ServiceInformer
	serviceLister   v13.ServiceLister
	serviceSynced   cache.InformerSynced
	// Ingress
	ingressInformer v1.IngressInformer
	ingressLister   v14.IngressLister
	ingressesSynced cache.InformerSynced
}

// NewKubeController 创建clientSet时 已经使用了kubeConfig了
func NewKubeController(kubeConfig *rest.Config, clientSet *kubernetes.Clientset, defaultReSync time.Duration) *KubeController {
	kc := &KubeController{kubeConfig: kubeConfig, clientSet: clientSet}
	// 生成informerFactory
	kc.factory = informers.NewSharedInformerFactory(clientSet, defaultReSync)
	// 初始化 Deployment Informer
	kc.deploymentInformer = kc.factory.Apps().V1().Deployments()
	kc.deploymentsLister = kc.deploymentInformer.Lister()
	kc.deploymentsSynced = kc.deploymentInformer.Informer().HasSynced
	// 初始化 Pod Informer
	kc.podInformer = kc.factory.Core().V1().Pods()
	kc.podLister = kc.podInformer.Lister()
	kc.podSynced = kc.podInformer.Informer().HasSynced
	// 初始化 Service Informer
	kc.serviceInformer = kc.factory.Core().V1().Services()
	kc.serviceLister = kc.serviceInformer.Lister()
	kc.serviceSynced = kc.serviceInformer.Informer().HasSynced
	// 初始化 Ingress Informer
	kc.ingressInformer = kc.factory.Networking().V1().Ingresses()
	kc.ingressLister = kc.ingressInformer.Lister()
	kc.ingressesSynced = kc.ingressInformer.Informer().HasSynced
	return kc
}

func (kc *KubeController) Run(stopPodCh chan struct{}) {
	defer runtime.HandleCrash()
	// 启动
	kc.factory.Start(stopPodCh)
	if !cache.WaitForCacheSync(stopPodCh, kc.deploymentsSynced, kc.podSynced, kc.serviceSynced, kc.ingressesSynced) {
		runtime.HandleError(fmt.Errorf("kubernetes资源同步等待超时"))
	}
	kc.status = 1
	<-stopPodCh
}
